package com.simon.train.business.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.simon.train.business.domain.*;
import com.simon.train.business.dto.TrainSeatQueryDto;
import com.simon.train.business.dto.TrainSeatSaveDto;
import com.simon.train.business.enums.SeatColEnum;
import com.simon.train.business.mapper.TrainSeatMapper;
import com.simon.train.business.vo.TrainSeatQueryVO;
import com.simon.train.common.util.SnowUtil;
import com.simon.train.common.vo.PageVO;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class TrainSeatService {

    private static final Logger LOG = LoggerFactory.getLogger(TrainSeatService.class);

    @Resource
    private TrainSeatMapper trainSeatMapper;

    @Resource
    private TrainCarriageService trainCarriageService;

    public void SaveTrainSeat(TrainSeatSaveDto trainSeatSaveDto){
        TrainSeat trainSeat = BeanUtil.copyProperties(trainSeatSaveDto, TrainSeat.class);
        if (ObjectUtil.isNull(trainSeat.getId())){
            //对于首次保存 也就是新增 需要对字段单独做处理
            trainSeat.setId(SnowUtil.getSnowflakeNextId());
            DateTime time = DateTime.now();
            trainSeat.setCreateTime(time);
            trainSeat.setUpdateTime(time);
            trainSeatMapper.insert(trainSeat);
        } else {
            trainSeat.setUpdateTime(DateTime.now());
            trainSeatMapper.updateByPrimaryKey(trainSeat);
        }

    }

    public PageVO<TrainSeatQueryVO> QueryTrainSeatList(TrainSeatQueryDto trainSeatQueryDto){
        TrainSeatExample trainSeatExample = new TrainSeatExample();
        trainSeatExample.setOrderByClause("train_code asc, carriage_index asc, carriage_seat_index asc");
        TrainSeatExample.Criteria criteria = trainSeatExample.createCriteria();
        if (ObjectUtil.isNotEmpty(trainSeatQueryDto.getTrainCode())) {
            LOG.info("TrainCode:{}",trainSeatQueryDto.getTrainCode());
            criteria.andTrainCodeEqualTo(trainSeatQueryDto.getTrainCode());
        }
        LOG.info("当前请求的页码：{}", trainSeatQueryDto.getPage());
        LOG.info("每页条数：{}", trainSeatQueryDto.getPageSize());

        PageHelper.startPage(trainSeatQueryDto.getPage(),trainSeatQueryDto.getPageSize());
        List<TrainSeat> trainSeatList = trainSeatMapper.selectByExample(trainSeatExample);

        PageInfo<TrainSeat> pageInfo = new PageInfo<>(trainSeatList);
        LOG.info("总行数：{}", pageInfo.getTotal());
        LOG.info("总页数：{}", pageInfo.getPages());

        List<TrainSeatQueryVO> lists = BeanUtil.copyToList(trainSeatList, TrainSeatQueryVO.class);
        PageVO<TrainSeatQueryVO> pageVO = new PageVO<>();
        pageVO.setList(lists);
        pageVO.setTotal(pageInfo.getTotal());

        return pageVO;
    }

    public void deleteTrainSeat(Long id) {
        trainSeatMapper.deleteByPrimaryKey(id);
    }

    /**
     * 批量生成座位数据
     * 通过事务 要么全部成功 要么全部失败
     * @param trainCode
     */
    @Transactional
    public void GenerateTrainSeat(String trainCode){
        //1.清空对应的车次下所有的座位记录
        TrainSeatExample trainSeatExample = new TrainSeatExample();
        TrainSeatExample.Criteria criteria = trainSeatExample.createCriteria();
        criteria.andTrainCodeEqualTo(trainCode);
        trainSeatMapper.deleteByExample(trainSeatExample);

        //2.查找当前车次下的所有的车厢
        List<TrainCarriage> trainCarriages = trainCarriageService.QueryAllCarriageByTrainCode(trainCode);
        LOG.info("当前车次下的车厢数：{}", trainCarriages.size());

        //3.循环每个车厢中的座位
        for (TrainCarriage trainCarriage : trainCarriages) {
            //3.1 获取车厢的数据，行数，座位类型（也就得到了列数）
            Integer rowCount = trainCarriage.getRowCount();
            String seatType = trainCarriage.getSeatType();

            //3.2 根据车箱的座位类型，筛选出所有的列，比如车箱类型是一等座，则筛选出columnList={ACDF}
            List<SeatColEnum> colsByType = SeatColEnum.getColsByType(seatType);
            LOG.info("根据车厢的座位类型，筛选出所有的列：{}", colsByType);

            //3.3 循环行数
            DateTime now = DateTime.now();
            int seatIndex = 1;
            for (int row = 1; row <= rowCount; row++) {
                //3.4 循环列数
                for (SeatColEnum seatColEnum : colsByType) {
                    //3.5 构造座位数据并且保存到数据库
                    /**
                     * 插件 GenerateAllSetter
                     * 通过Alt+Enter 快速生成带默认值或不带默认值的set方法等
                     */
                    TrainSeat trainSeat = new TrainSeat();
                    trainSeat.setId(SnowUtil.getSnowflakeNextId());
                    trainSeat.setTrainCode(trainCode);
                    trainSeat.setCarriageIndex(trainCarriage.getIndex());
                    trainSeat.setRow(StrUtil.fillBefore(String.valueOf(row), '0', 2));
                    trainSeat.setCol(seatColEnum.getCode());
                    trainSeat.setSeatType(seatType);
                    trainSeat.setCarriageSeatIndex(seatIndex++);
                    /**
                     * 你使用的是 DateTime 类（来自 Hutool 工具库）
                     * 而 TrainSeat 类中的 createTime 和 updateTime 是 java.util.Date 类型
                     * 虽然 DateTime 是 Date 的子类（Hutool 的 DateTime 继承自 java.util.Date）
                     * 所以可以直接赋值给 Date 类型的字段，这在语法上是允许的，不会导致编译错误
                     * DateTime 继承自 Date，所以可以自动向上转型
                     */
                    trainSeat.setCreateTime(now);
                    trainSeat.setUpdateTime(now);
                    trainSeatMapper.insert(trainSeat);
                }

            }
        }
    }

    /**
     * 根据trainCode直接查询出所有的座位信息
     * @param trainCode
     * @return
     */
    public List<TrainSeat> SelectByTrainCode(String trainCode) {
        TrainSeatExample trainSeatExample = new TrainSeatExample();
        trainSeatExample.setOrderByClause("`id` asc");
        trainSeatExample.createCriteria().andTrainCodeEqualTo(trainCode);
        /**
         * Mybatis默认查询结果为空时 会返回空 而不是空指针 从而不会出现空指针异常
         */
        return trainSeatMapper.selectByExample(trainSeatExample);
    }
}
